Private z_scFunk As Collection 'hWnd/thunk-address collection; initialized as needed
Private Const IDX_INDEX As Long = 2 'index of the subclassed hWnd OR hook type
Private Const IDX_PREVPROC As Long = 9 'Thunk data index of the original WndProc
Private Const IDX_BTABLE As Long = 11 'Thunk data index of the Before table for messages
Private Const IDX_ATABLE As Long = 12 'Thunk data index of the After table for messages
Private Const IDX_CALLBACKORDINAL As Long = 36 ' Ubound(callback thunkdata)+1, index of the callback
' Declarations:
Private Declare Sub RtlMoveMemory Lib "kernel32" (ByVal Destination As Long, ByVal Source As Long, ByVal Length As Long)
Private Declare Function IsBadCodePtr Lib "kernel32" (ByVal lpfn As Long) As Long
Private Declare Function VirtualAlloc Lib "kernel32" (ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
Private Declare Function VirtualFree Lib "kernel32" (ByVal lpAddress As Long, ByVal dwSize As Long, ByVal dwFreeType As Long) As Long
Private Declare Function GetModuleHandleA Lib "kernel32" (ByVal lpModuleName As String) As Long
Private Declare Function GetModuleHandleW Lib "kernel32" (ByVal lpModuleName As Long) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Enum eThunkType
SubclassThunk = 0
End Enum
'-Selfsub specific declarations----------------------------------------------------------------------------
Private Enum eMsgWhen 'When to callback
MSG_BEFORE = 1 'Callback before the original WndProc
MSG_AFTER = 2 'Callback after the original WndProc
MSG_BEFORE_AFTER = MSG_BEFORE Or MSG_AFTER 'Callback before and after the original WndProc
End Enum
' see ssc_Subclass for complete listing of indexes and what they relate to
Private Const IDX_PARM_USER As Long = 13 'Thunk data index of the User-defined callback parameter data index
Private Const IDX_UNICODE As Long = 107 'Must be UBound(subclass thunkdata)+1; index for unicode support
Private Const MSG_ENTRIES As Long = 32 'Number of msg table entries. Set to 1 if using ALL_MESSAGES for all subclassed windows
Private Const ALL_MESSAGES As Long = -1 'All messages will callback
Private Declare Function GetCurrentProcessId Lib "kernel32" () As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Private Declare Function IsWindow Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function IsWindowUnicode Lib "user32.dll" (ByVal hwnd As Long) As Long
Private Declare Function SetWindowLongA Lib "user32" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function SetWindowLongW Lib "user32" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private m_Color As Long 'Private shadow color property value
Private m_Depth As Long 'Private shadow depth property value
Private m_Transparency As Long 'Private shadow transparency property value
Private bIsLayered As Boolean 'Layered windows supported
Private bIsLuna As Boolean 'Luna theme?
Private bIsXP As Boolean 'Windows XP (or greater)?
Private bLastShow As Boolean 'The previous show state
Private cx As Long 'Width
Private cy As Long 'Height
Private hWndBt As Long 'Bottom shadow window handle
Private hWndRt As Long 'Right shadow window handle
Private hWndForm As Long 'Parent window handle
Private wp As tWINDOWPOS 'Parent window position
Private Declare Function CreateDIBSection Lib "gdi32" (ByVal hdc As Long, pBitmapInfo As tBITMAPINFOHEADER, ByVal un As Long, ByRef lplpVoid As Long, ByVal handle As Long, ByVal dw As Long) As Long
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function CreateWindowExA Lib "user32" (ByVal dwExStyle As Long, ByVal lpClassName As String, ByVal lpWindowName As String, ByVal dwStyle As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hWndParent As Long, ByVal hMenu As Long, ByVal hInstance As Long, lpParam As Any) As Long
Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function DestroyWindow Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
Private Declare Function GetCurrentThemeName Lib "uxtheme.dll" (ByVal pszThemeFileName As Long, ByVal cchMaxNameChars As Long, ByVal pszColorBuff As Long, ByVal cchMaxColorChars As Long, ByVal pszSizeBuff As Long, ByVal cchMaxSizeChars As Long) As Long
Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetDeviceCaps Lib "gdi32" (ByVal hdc As Long, ByVal nIndex As Long) As Long
Private Declare Function GetSysColor Lib "user32" (ByVal nIndex As Long) As Long
Private Declare Function GetThemeDocumentationProperty Lib "uxtheme.dll" (ByVal pszThemeName As Long, ByVal pszPropertyName As Long, ByVal pszValueBuff As Long, ByVal cchMaxValChars As Long) As Long
Private Declare Function GetVersionExA Lib "kernel32" (lpVersionInformation As tOSVERSIONINFO) As Long
Private Declare Function IsWindowVisible Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function LoadLibraryA Lib "kernel32" (ByVal lpLibFileName As String) As Long
Private Declare Function MoveWindow Lib "user32" (ByVal hwnd As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal bRepaint As Long) As Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
Private Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
Private Declare Function UpdateLayeredWindow Lib "user32.dll" (ByVal hwnd As Long, ByVal hdcDest As Long, ptDst As Any, pSize As Any, ByVal hDCSrc As Long, ptSrc As Any, ByVal crKey As Long, pBlend As Any, ByVal dwFlags As Long) As Long
Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (Ptr() As Any) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Sub Class_Initialize() 'Class initialization
CheckEnvironment
m_Depth = DEF_DEPTH
m_Transparency = DEF_TRANSPARENCY
End Sub
Private Sub Class_Terminate()
ssc_Terminate 'Terminate all subclassing
If hWndRt <> 0 Then
DestroyWindow hWndRt
DestroyWindow hWndBt
End If
End Sub
'Shadow depth property
Public Property Get Color() As Long
Color = m_Color
End Property
'
Public Property Let Color(ByVal newValue As Long)
Const COLOR_SYS_MASK As Long = &H80000000
If (newValue And COLOR_SYS_MASK) Then 'If the system color bit is set
newValue = GetSysColor(newValue Xor COLOR_SYS_MASK) 'Get the translated system color
End If
If newValue <> m_Color Then
m_Color = newValue
DisplayShadows
End If
End Property
'Shadow depth property
Public Property Get Depth() As Long
Depth = m_Depth
End Property
'
Public Property Let Depth(ByVal newValue As Long)
If newValue <> m_Depth Then
m_Depth = newValue
DisplayShadows
End If
End Property
'Shadow transparency property
Public Property Get Transparency() As Byte
Transparency = CByte(m_Transparency)
End Property
'
Public Property Let Transparency(ByVal newValue As Byte)
If newValue <> m_Transparency Then
m_Transparency = CLng(newValue)
DisplayShadows
End If
End Property
'Set the form to be shadowed
Public Function Shadow(frm As Form) As Boolean
If hWndForm <> 0 Then
zError "Shadow", "Only a single form per cShadow instance is allowed"
hDib = CreateDIBSection(DC, bmpHeader, 0, pBmpBits, 0, 0) 'Create a device independant bitmap as per the header, compatible with the dc (compatible with the screen)
With SafeArray 'Construct a VB safearray header that matches the specs of the bitmap
.cbElements = 4 '4 bytes per element - 32bits per pixel
.cDims = 2 'We'll treat the pixels as a two dimensional (x, y) array
.pvData = pBmpBits 'The data pointer points to the bitmap data (pixels)
.Bounds(0).lLbound = 0 'Lowest bound will be 0
.Bounds(0).cElements = cy 'The number of elements
.Bounds(1).lLbound = 0 'Lowest bound will be 0
.Bounds(1).cElements = cx 'The number of elements
End With
CopyMemory ByVal VarPtrArray(aPixels()), VarPtr(SafeArray), 4 'Copy the address of our safearray over the address of aPixels() safearray
arPtr(C8As4 oo rPl EI data indes V, Bepce, vbInteg'((((((((((((1Dove thwD4I
End
EnM6bbbbbEcounDM
End
EnM6I WP) = z
ata(I Long2 = second 555t as2_I Ds8
'Bf zFnnAdd6 g2 = second 555t ad
End ppppppppAs DXz:message toE to theen
_ rPtr(C8A4_6sVATE (ioooo rPl
(
loop
End If+'EsVATE (io8
'Bf zFnE to theen
_d 557N6
(
Ae ind rPtr(C8AsnON As Long C' Ifn sg o f the8) Then 1 ........0 EnzeeeeezFnAal WndProc
ar(Ct DDDDDDDDDDDndex of the After table(Ct DDDD 'Bail...
End If
f ALL_MEPR &a Form sVATE (ioooo rPl
em + Izdata uelement for Ar o f the8) Then 1 ........0 EnzeeeeezFnAaoc
(ioooo rPl r &a Form sVATE (ioooo rPl
em + Izdat72o rPl r &a Form sVATE (ioooo rPl
em method
Ifr(nValueElse
zEr Const IDX_FREE As Long = 6 c
th zFnA555555a
th zFnA555555a
th zFnA55555 aaaaaaaaa to theenta indic B eenta ito theenta in1 ...d
in1oooo rPl zAddress ito 'Get the hodwo lines canSFnA5555ConsVATE (ioo3 o f the8) Then ess aaaaa eef the8) Thenl
aef the8) Thenl
a canSFn'5 zAddf the8)'As Long,bbbef thess
I data indes5555ConsVATE (iool M 'Bump to -5vNVt as2_I Dsg Tcaaa C
aef the .......SPB 'Ensure the new WndProc was set a canSFnwas set a canSFnwas setSs set 0#DWr("usereU
rPl 7+e expe(ioooo rPl anSFnwas setSs set rPl 7+e eo -5vNVt as2_I Dsget ) = zFnAdd
6 c,unkdata)+1; Exit Sub
End If
End If
bLastShow = bShow
uu1as set a canSFnwas setM6I er tabsn't al tong C6o 5vNVt a tong C'Get the awas set / set7 aaaaa eef the8) Thenlpter tab f 5vNVt a tong C'GWdinal * 41 ioo3 bject address i ) = zI er tabsnP 4), 48er tabsnP 4), 48er tabsnP 4), 48er tabsnP 4), 48er 'ering added 'Map zMB 'Bail...
End) snP 4),7"End)oo rPl whbject address8x$(uMs C place 'Bail...
End) snP 4),7"End)oo rPl whbjp'If
't a&HFFFFFdnic 3<kCoil...e)zIbject a=Vt toti whbjectw rPc 'eringIong C'GWdinal * tbjecOo'Bail... txu whbjecMa snP 1e As LongEnd)oo rPl whbjp'If
to 4), 48e bl(A 'Bailtoti whb ee"keimaOs Long = 5 'Thunk dat5Fnwas secoo ,e
End Subsz) Thenl _Sc(104) = &H81612445: z_Sc(105) = &H4C4&: z_tr(nAddr), i, 4 'o_f
I, 'Ensure the allocation succeeded
End=I6Bump d If
im i c users. S "I index NhNVt aM1
location succeeded
p I, i,<sE tded
nl _S0thoA5555nteg'((( plac9dddddddddddd users ee"keimaOs Long = 5 ' 557N6
u nP 4)Sate exeon succeeded
p I, i,<sE tded
ned
ned
ned
neS5edddddduMsoA#en
exeon succe* tbjecOo'Bailx NhNVt a y cddddduMsoA#de API)CsCT7as2_IngasUnic I oAs LongnedTo UBound(MecM t y allocation ss the exeon succe*sCT7as2_IngasUnic I oAs LongnedTo UBound(MeW) = zFnAddr("user32", "DestroyWindow", bUnicode)
End IDE_LEng_ As Stris allocI)tance
As LongnedTo UBound(MecM t yyyyyC64 oo yKh zFC bSub As ng_ As Stris allocI)L
Ifnction
' ycond indow h ycond ' C bSub As ng_ As Stris allocI)L
IWndPr z t yyyyyC64 oo pf ction9 'eri exeon succe*sCT7as2_IngasUcce*sCT8e awae with de API)CsCT7as2_IngasUnic I oAs LongnedTo UBound(MecM t y allocation ss the exeon succe*sCT7as2_IngasUnic I oAs LongnedTo UBound(a'yC64 oo yKh zFC bSub As ng_ As Stris allocI)L
Ifnc= 5 B=Vt uttabsnP a As LonIl nOrdiecM t ' 5edTo U Ifnc= 5 ) allocI)L
Ifnc= 5 dex g_ As Stris adex unicode reqi63_Sc(34) t yyySub As ng_ As'8em +ecM _6sVATxR 'Next message table entry
s Stris adex unLUBound(a'yC64 oo yKh ctioenc= 5 7(ByVal nIndex AsS
Selcx-ers.thaA#de 3or "zzzzzt utdddddddqL ctioenc=yKh ctis DXz8 by the vvvvvvvvvv:5=Mnt to ALL_MEvvvvv:5=Mnb.tA4"o
yyySub As ng nRe .cx, .tA4"o
n
c '3If+'bnMustoI
End
EnM6bbbbb(Addr("user32", "DestroyWinur("u7.End
Sr Selcx-eub As ng _5 p 'lfinal) 'Get the addresbu' he vvvvvvvvvv:5=Mnt to ALLs S5C45: zzzzzRetbjeccccccddddddddddddddddddddddddlimng C'GWd1e As LongEnd"keimng45:8er tabsnP 4), aaaaa ...d
in1oooo Long nRe .cx, .Ync ' '2_I Dsng ddddddlimng C'w next mesv:5=M_Sc(3LnRe .cx, .Yn -